package top.hcode.hoj.service.admin;

import cn.hutool.core.lang.Validator;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import top.hcode.hoj.common.LazyDao;
import top.hcode.hoj.dao.org.OrgDao;
import top.hcode.hoj.dao.org.OrgUserDao;
import top.hcode.hoj.pojo.dto.org.AdmOrgUserSaveDTO;
import top.hcode.hoj.pojo.entity.org.Org;
import top.hcode.hoj.pojo.entity.org.OrgUser;
import top.hcode.hoj.pojo.form.AdmQueryOrgUserForm;
import top.hcode.hoj.pojo.vo.org.AdmOrgUserVO;
import top.hcode.hoj.utils.PageUtil;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static top.hcode.hoj.utils.SqlUtil.sql;

/**
 * @author orangej
 * @since 2025-01-21
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AdminOrgUserService {
    private final LazyDao dao;
    private final OrgUserDao orgUserDao;
    private final OrgDao orgDao;

    public IPage<AdmOrgUserVO> getOrgUserList(AdmQueryOrgUserForm form) {
        List<String> treeCodeList = orgDao.queryTreeCodeList(Lang.list(form.getSchoolId(), form.getGradeId(), form.getClassId())
                .stream().filter(Objects::nonNull).collect(Collectors.toList()));

        IPage<AdmOrgUserVO> result = PageUtil.toMybatis(dao.selectPage(form.getCurrentPage(), form.getLimit(),
                AdmOrgUserVO.class, "queryOrgUserByTreeCode",
                NutMap.NEW().addv("treeCodeList", treeCodeList)
                        .addv("userType", form.getUserType())
                        .addv("keyword", form.getKeyword())));
        if (result.getTotal() > 0) {
            // 查询班级信息
            List<AdmOrgUserVO> userList = result.getRecords();
            List<String> userIdList = userList.stream().map(OrgUser::getId).collect(Collectors.toList());
            List<NutMap> userIdClassNameList = dao.queryMap(sql("select t0.*, t1.org_name as className, t3.org_name as schoolName from " +
                                                                "(select user_id, org_id from class_has_user where user_id in (?)) t0 " +
                                                                "left join org t1 on t0.org_id = t1.id " +
                                                                "left join org_class t2 on t0.org_id = t2.id " +
                                                                "left join org t3 on t2.school_id = t3.id"), userIdList);
            userIdClassNameList.stream().forEach(m -> {
                String classId = m.getString("orgId");
                String className = m.getString("className");
                String schoolName = m.getString("schoolName");
                String userId = m.getString("userId");
                userList.stream().filter(u -> u.getId().equals(userId))
                        .forEach(u -> {
                            u.setClassId(classId);
                            u.setClassName(className);
                            u.setSchoolName(schoolName);
                        });
            });
        }

        return result;
    }

    public OrgUser getOrgUser(Long id) {
        return orgUserDao.getById(id);
    }

    @Transactional
    public OrgUser saveOrgUser(AdmOrgUserSaveDTO orgUser) {
        orgUserDao.saveOrUpdate(orgUser);
        String classId = orgUser.getClassId();
        if (Strings.isNotBlank(classId)) {
            saveUserClass(orgUser.getId(), orgUser.getUserType(), classId);
        }

        return orgUser;
    }

    public void deleteOrgUser(Long id) {
        orgUserDao.removeById(id);
    }

    /**
     * 保存用户班级关系，会自动保存用户学校关系和校区关系
     *
     * @param userId   用户id
     * @param userType 用户类型
     * @param classId  班级id
     */
    @Transactional
    public void saveUserClass(String userId, int userType, String classId) {
        Org clazz = orgDao.getById(classId);
        Validator.validateNotNull(clazz, "班级不存在 : {}", classId);

        // 如果用户已经存在班级关系，则返回
        if (dao.fetchInt(sql("select count(1) from class_has_user where user_id = ? and org_id = ?"), userId, classId) > 0) {
            return;
        }

        boolean isStudent = userType == 0;

        // 学生只能绑定1个班级
        if (isStudent) {
            dao.runSql(sql("delete from class_has_user where user_id = ?"), userId);
            dao.runSql(sql("delete from school_has_user where user_id = ?"), userId);
            dao.runSql(sql("delete from org_has_user where user_id = ?"), userId);
        }

        // class_has_user
        dao.runSql(sql("insert into class_has_user (user_id, org_id, user_type, tree_code) values (?, ?, ?, ?)"),
                userId, classId, userType, clazz.getTreeCode());


        // school_has_user
        Org school = orgDao.getByTreeCode(clazz.getTreeCode().substring(0, 4));
        if (dao.fetchInt(sql("select count(1) from school_has_user where user_id = ? and org_id = ?"), userId, school.getId()) == 0) {
            dao.runSql(sql("insert into school_has_user (org_id, user_id, user_type) values (?, ?, ?)"), school.getId(), userId, userType);
        }

        // org_has_user
        Org campus = orgDao.getByTreeCode(clazz.getTreeCode().substring(0, 8));
        if (dao.fetchInt(sql("select count(1) from org_has_user where user_id = ? and org_id = ?"), userId, campus.getId()) == 0) {
            dao.runSql(sql("insert into org_has_user (org_id, user_id, tree_code, user_type, org_type) values (?, ?, ?, ?, ?)"),
                    campus.getId(), userId, campus.getTreeCode(), userType, campus.getOrgType());
        }
    }
}
